From be7dcf1b16acac72fe59d5bee6328d46ddf372cd Mon Sep 17 00:00:00 2001 From: Dominique Belhachemi Date: Tue, 23 Sep 2025 17:36:03 -0400 Subject: [PATCH] Import all debian/ directory changes from master --- debian/changelog | 113 ++ debian/control | 50 +- debian/copyright | 14 +- debian/libvtk9.1t64-qt.lintian-overrides | 2 + debian/libvtk9.1t64.lintian-overrides | 2 + debian/patches/09_newer_expat.patch | 68 ++ .../patches/100_add_missing_gl_header.patch | 24 +- .../patches/121_add_support_for_loong64.patch | 22 + debian/patches/130_fix_python_3.13.patch | 1058 +++++++++++++++++ debian/patches/42_fix_octree_node.patch | 13 + debian/patches/netcdf-4.9.3.patch | 172 +++ debian/patches/series | 5 + debian/rules | 16 +- 13 files changed, 1496 insertions(+), 63 deletions(-) create mode 100644 debian/libvtk9.1t64-qt.lintian-overrides create mode 100644 debian/libvtk9.1t64.lintian-overrides create mode 100644 debian/patches/09_newer_expat.patch create mode 100644 debian/patches/121_add_support_for_loong64.patch create mode 100644 debian/patches/130_fix_python_3.13.patch create mode 100644 debian/patches/42_fix_octree_node.patch create mode 100644 debian/patches/netcdf-4.9.3.patch diff --git a/debian/changelog b/debian/changelog index 953790f12..f8e488d03 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,119 @@ vtk9 (9.5.2+dfsg1-1~exp1) UNRELEASED; urgency=medium -- Dominique Belhachemi Tue, 23 Sep 2025 16:48:13 -0400 +vtk9 (9.3.0+dfsg1-7) unstable; urgency=medium + + * Non-maintainer upload + * Remove obsolete libosmesa6-dev dependency. (Closes: #1113920) + * Remove obsolete tcl-dev and tk-dev dependency. + * Remove r-base dependency + * Apply upstream patch to fix gcc-15 FTBFS issue (Closes: #1111572) + * Remove obsolete libftgl-dev dependency + + -- Dominique Belhachemi Thu, 04 Sep 2025 14:06:08 -0400 + +vtk9 (9.3.0+dfsg1-6) unstable; urgency=medium + + * Team upload. + * Remove obsolete libmrmpi-dev dependency. + + -- Bastian Germann Mon, 01 Sep 2025 17:22:13 +0200 + +vtk9 (9.3.0+dfsg1-5) unstable; urgency=medium + + * Team upload. + [ Adrian Bunk ] + * Apply patch from Samuel Thibault to disable Java and TBB on Hurd. + Closes: #1094994. + * Make TBB architecture settings consistent. + * Remove handling of removed kfreebsd. + + -- Santiago Vila Fri, 22 Aug 2025 13:20:00 +0200 + +vtk9 (9.3.0+dfsg1-4) unstable; urgency=medium + + * Team upload. + * Replace _FillValue by NC_FillValue for NetCDF 4.9.3. (Closes: #1095478) + + -- Bastian Germann Sat, 15 Feb 2025 13:13:19 +0000 + +vtk9 (9.3.0+dfsg1-3) unstable; urgency=medium + + * [a52f6c5] Fix segfault on python 3.13. (Closes: #1092354) + + -- Anton Gladky Tue, 28 Jan 2025 21:40:49 +0100 + +vtk9 (9.3.0+dfsg1-2) unstable; urgency=medium + + * Team upload. + * Drop Depends: libqt5webkit5-dev. + + -- Bastian Germann Thu, 23 Jan 2025 08:49:29 +0100 + +vtk9 (9.3.0+dfsg1-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * Build against libhdf5-mpi-dev, since libhdf5-openmpi-dev is no longer + available on 32-bit architectures. Closes: #1078743. + + -- Emilio Pozuelo Monfort Fri, 22 Nov 2024 11:49:45 +0100 + +vtk9 (9.3.0+dfsg1-1) unstable; urgency=medium + + * Team upload. + + [ Michael R. Crusoe ] + * Build the IO/GeoJSON module. Closes: #1029285 + To the binary package libvtk9.1t64, this adds + /usr/lib/${DEB_HOST_MULTIARCH}/libvtkIOGeoJSON-9.1.so.9.1.0 + /usr/lib/${DEB_HOST_MULTIARCH}/vtk/hierarchy/VTK/vtkIOGeoJSON-hierarchy.txt + /usr/lib/${DEB_HOST_MULTIARCH}/libvtkIOGeoJSON-9.1.so.1 + To the binary package libvtk9-dev, this adds + /usr/include/vtk-9.1/vtkGeoJSONFeature.h + /usr/include/vtk-9.1/vtkGeoJSONReader.h + /usr/include/vtk-9.1/vtkGeoJSONWriter.h + /usr/include/vtk-9.1/vtkIOGeoJSONModule.h + /usr/lib/${DEB_HOST_MULTIARCH}/libvtkIOGeoJSON-9.1.so + To the binary package libvtk9-java, this adds + /usr/lib/${DEB_HOST_MULITARCH}/java/vtk-Linux-${DEB_HOST_GNU_CPU} + /libvtkIOGeoJSONJava.so + To the binary package python3-vtk9, this adds + /usr/lib/python3/dist-packages/vtkmodules + /vtkIOGeoJSON.cpython-311-${DEB_HOST_GNU_CPU}.so + + [ Anton Gladky ] + * Upload of new version 9.3 into unstable. + + -- Anton Gladky Thu, 06 Jun 2024 21:34:35 +0200 + +vtk9 (9.1.0+really9.1.0+dfsg2-8) unstable; urgency=medium + + [ Bo YU ] + * Team upload. + * Add support for loongarch64. Thanks to Dandan Zhang + . (Closes: #1054471) + + [ Michael R. Crusoe ] + * Cherry-pick patch from upstream to fix issue with newer expat and + appended data. Closes: #1064762 + * d/control: build-dep on libhdf5-mpi-dev instead of libhdf5-openmpi- + dev. Closes: #1068321 + * Cherry-pick patch from upstream to fix CVE-2021-42521. Closes: + #1031877. + * Fix Maintainer name of Debian Science team (routine-update) + * Remove trailing whitespace in debian/copyright (routine-update) + * d/control: Updated some dependencies on obsolete or supercede packages + names. + + -- Michael R. Crusoe Mon, 29 Apr 2024 16:16:28 +0200 + +vtk9 (9.1.0+really9.1.0+dfsg2-7.1) unstable; urgency=medium + + * Non-maintainer upload. + * Rename libraries for 64-bit time_t transition. Closes: #1063267 + + -- Steve Langasek Wed, 28 Feb 2024 23:38:25 +0000 + vtk9 (9.3.0+dfsg1-1~exp4) experimental; urgency=medium * [43fb8c1] Add libgl2ps-dev as depends. diff --git a/debian/control b/debian/control index 44b19d6ea..b0f1c287b 100644 --- a/debian/control +++ b/debian/control @@ -1,14 +1,15 @@ Source: vtk9 -Maintainer: Debian Science Team +Maintainer: Debian Science Maintainers Uploaders: Anton Gladky , Gert Wollny , Nico Schlömer Section: graphics Priority: optional -Build-Depends: chrpath, - cmake (>= 3.2.0), +Build-Depends: dpkg-dev (>= 1.22.5), + chrpath, + cmake, debhelper-compat (= 13), - default-jdk [!hppa !hurd-any !kfreebsd-any], + default-jdk [!hppa !hurd-any], default-libmysqlclient-dev, dh-sequence-python3, doxygen-latex, @@ -28,22 +29,19 @@ Build-Depends: chrpath, libexpat-dev, libfontconfig-dev, libfreetype-dev, - libftgl-dev, libgdal-dev, - libgl1-mesa-dev | libgl-dev, + libgl-dev, libgl2ps-dev, libglew-dev, - libglu1-mesa-dev | libglu-dev, - libhdf5-openmpi-dev, + libglu-dev, + libhdf5-mpi-dev, libhpdf-dev, libjpeg-dev, libjs-mathjax, libjsoncpp-dev, liblz4-dev, - libmrmpi-dev, libnetcdf-dev (>= 1:4.9.0), libogg-dev, - libosmesa6-dev, libpng-dev, libpq-dev, libproj-dev, @@ -60,19 +58,14 @@ Build-Depends: chrpath, libxt-dev, lzma, mpi-default-dev, - pkg-config, + pkgconf, python3-dev, python3-matplotlib, python3-mpi4py, qtbase5-dev, libqt5opengl5-dev, qtdeclarative5-dev, - r-base-core, - r-base-dev, - r-base, - tcl-dev, texlive-binaries, - tk-dev, x11proto-core-dev, xauth, xvfb, @@ -86,10 +79,11 @@ Rules-Requires-Root: no Package: libvtk9-dev Architecture: any +Multi-Arch: same Section: libdevel Depends: ${misc:Depends}, ${shlibs:Depends}, - default-jdk [!hppa !hurd-any !kfreebsd-any], + default-jdk [!hppa !hurd-any], default-libmysqlclient-dev, libavcodec-dev, libavformat-dev, @@ -115,12 +109,12 @@ Depends: ${misc:Depends}, libproj-dev, libpython3-dev, libswscale-dev, - libtbb-dev [!hurd-i386 !kfreebsd-i386 !kfreebsd-amd64 !alpha !ia64], + libtbb-dev [linux-any], libtheora-dev, libtiff-dev, libutfcpp-dev, libvtk9.3 (= ${binary:Version}), - libvtk9-java (= ${binary:Version}) [!hppa !hurd-any !kfreebsd-any], + libvtk9-java (= ${binary:Version}) [!hppa !hurd-any], libx11-dev, libxft-dev, libxml2-dev, @@ -128,8 +122,6 @@ Depends: ${misc:Depends}, libxt-dev, mpi-default-dev, python3-vtk9 (= ${binary:Version}), - tcl-dev, - tk-dev, vtk9 (= ${binary:Version}), x11proto-core-dev, zlib1g-dev @@ -146,13 +138,16 @@ Package: libvtk9.3 Architecture: any Multi-Arch: same Section: libs -Breaks: libvtk9 (<< 9.1.0+really9.1.0) -Replaces: libvtk9 (<< 9.1.0+really9.1.0) Depends: ${misc:Depends}, ${shlibs:Depends} Suggests: mpi-default-bin, vtk9-doc, vtk9-examples +Breaks: libvtk9.1 (<< ${source:Version}), + libvtk9 (<< 9.1.0+really9.1.0) +Provides: ${t64:Provides} +Replaces: libvtk9.1, + libvtk9 (<< 9.1.0+really9.1.0) Description: VTK libraries The Visualization Toolkit (VTK) is an open-source software system for 3D computer graphics, image processing, and visualization. @@ -161,7 +156,7 @@ Description: VTK libraries that use VTK. Package: libvtk9-java -Architecture: amd64 arm64 armel armhf i386 mips64el mipsel ppc64el s390x alpha ia64 m68k powerpc ppc64 riscv64 sh4 sparc64 x32 +Architecture: amd64 arm64 armel armhf i386 loong64 mips64el mipsel ppc64el s390x alpha ia64 m68k powerpc ppc64 riscv64 sh4 sparc64 x32 Section: java Depends: ${java:Depends}, ${misc:Depends}, @@ -173,7 +168,7 @@ Suggests: java-virtual-machine, vtk9-examples Description: VTK - Java language support The Visualization Toolkit (VTK) is an object oriented, high level - library that allows one to easily write C++ programs, Tcl, Python and + library that allows one to easily write C++ programs, Python and Java scripts that do 3D visualization. . This package provides the VTK Java language support. @@ -248,12 +243,16 @@ Multi-Arch: same Section: libs Depends: ${misc:Depends}, ${shlibs:Depends} +Breaks: libvtk9.1-qt (<< ${source:Version}) +Provides: ${t64:Provides} +Replaces: libvtk9.1-qt Description: VTK libraries, Qt files The Visualization Toolkit (VTK) is an open-source software system for 3D computer graphics, image processing, and visualization. . This package provides the shared libraries needed to run C++ programs that use VTK. Qt files +X-Time64-Compat: libvtk9.1-qt Package: libvtk9-qt-dev Architecture: any @@ -266,7 +265,6 @@ Depends: libvtk9-dev (= ${binary:Version}), qtbase5-dev, qttools5-private-dev, libqt5opengl5-dev, - libqt5webkit5-dev Description: VTK header files, containing Qt files The Visualization Toolkit (VTK) is an open-source software system for 3D computer graphics, image processing, and visualization. diff --git a/debian/copyright b/debian/copyright index d0fe9287f..b35974071 100644 --- a/debian/copyright +++ b/debian/copyright @@ -272,18 +272,18 @@ License: Apache-2 License: Zlib This software is provided 'as-is', without any express or implied warranty. . - In no event will the authors be held liable for any damages arising from the + In no event will the authors be held liable for any damages arising from the use of this software. . - Permission is granted to anyone to use this software for any purpose,including - commercial applications, and to alter it and redistribute it freely, subject + Permission is granted to anyone to use this software for any purpose,including + commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: . - 1. The origin of this software must not be misrepresented; you must not claim - that you wrote the original software. If you use this software in a - product, an acknowledgment in the product documentation would be + 1. The origin of this software must not be misrepresented; you must not claim + that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. diff --git a/debian/libvtk9.1t64-qt.lintian-overrides b/debian/libvtk9.1t64-qt.lintian-overrides new file mode 100644 index 000000000..b0273f599 --- /dev/null +++ b/debian/libvtk9.1t64-qt.lintian-overrides @@ -0,0 +1,2 @@ +libvtk9.1t64-qt: package-name-doesnt-match-sonames +libvtk9.1t64-qt: package-name-doesnt-match-sonames libvtk9.1-qt diff --git a/debian/libvtk9.1t64.lintian-overrides b/debian/libvtk9.1t64.lintian-overrides new file mode 100644 index 000000000..d9ce053c2 --- /dev/null +++ b/debian/libvtk9.1t64.lintian-overrides @@ -0,0 +1,2 @@ +libvtk9.1t64: package-name-doesnt-match-sonames +libvtk9.1t64: package-name-doesnt-match-sonames libvtk9.1 diff --git a/debian/patches/09_newer_expat.patch b/debian/patches/09_newer_expat.patch new file mode 100644 index 000000000..0e66e40d1 --- /dev/null +++ b/debian/patches/09_newer_expat.patch @@ -0,0 +1,68 @@ +From: Ben Boeckel +Date: Mon, 15 Apr 2024 22:22:22 -0400 +Subject: vtkXMLDataParser: track `AppendedData` state explicitly +Bug-Debian: https://bugs.debian.org/1064762 +Origin: upstream,https://gitlab.kitware.com/vtk/vtk/-/commit/3efa07ad277efe5c1d11a2ef2b907c095f68bbef +Forwarded: not-needed + +Newer `libexpat` doesn't like being given the appended data after the +artificially ended document anymore. Avoid pushing it through to its +parser. + +--- + IO/XMLParser/vtkXMLDataParser.cxx | 6 +++++- + IO/XMLParser/vtkXMLDataParser.h | 3 +++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +Index: vtk9/IO/XMLParser/vtkXMLDataParser.cxx +=================================================================== +--- vtk9.orig/IO/XMLParser/vtkXMLDataParser.cxx ++++ vtk9/IO/XMLParser/vtkXMLDataParser.cxx +@@ -36,6 +36,7 @@ vtkXMLDataParser::vtkXMLDataParser() + this->RootElement = nullptr; + this->AppendedDataPosition = 0; + this->AppendedDataMatched = 0; ++ this->AppendedDataFound = false; + this->DataStream = nullptr; + this->InlineDataStream = vtkBase64InputStream::New(); + this->AppendedDataStream = vtkBase64InputStream::New(); +@@ -88,6 +89,7 @@ void vtkXMLDataParser::PrintSelf(ostream + { + this->Superclass::PrintSelf(os, indent); + os << indent << "AppendedDataPosition: " << this->AppendedDataPosition << "\n"; ++ os << indent << "AppendedDataFound: " << this->AppendedDataFound << "\n"; + if (this->RootElement) + { + this->RootElement->PrintXML(os, indent); +@@ -214,7 +216,7 @@ int vtkXMLDataParser::ParsingComplete() + // If we have reached the appended data section, we stop parsing. + // This prevents the XML parser from having to walk over the entire + // appended data section. +- if (this->AppendedDataPosition) ++ if (this->AppendedDataPosition || this->AppendedDataFound) + { + return 1; + } +@@ -433,6 +435,8 @@ int vtkXMLDataParser::ParseBuffer(const + { + return 0; + } ++ ++ this->AppendedDataFound = true; + } + + return 1; +Index: vtk9/IO/XMLParser/vtkXMLDataParser.h +=================================================================== +--- vtk9.orig/IO/XMLParser/vtkXMLDataParser.h ++++ vtk9/IO/XMLParser/vtkXMLDataParser.h +@@ -204,6 +204,9 @@ protected: + // How much of the string " - TODO: Put a short summary on the line above and replace this paragraph - with a longer explanation of this change. Complete the meta-information - with other relevant fields (see below for details). To make it easier, the - information below has been extracted from the changelog. Adjust it or drop - it. - . - vtk9 (9.3.0+dfsg1-1~exp2) experimental; urgency=medium - . - * [ad5a07d] Update build-depends. +Description: Add missing GL header Author: Anton Gladky - ---- -The information above should follow the Patch Tagging Guidelines, please -checkout https://dep.debian.net/deps/dep3/ to learn about the format. Here -are templates for supplementary fields that you might want to add: - -Origin: (upstream|backport|vendor|other), (|commit:) -Bug: -Bug-Debian: https://bugs.debian.org/ -Bug-Ubuntu: https://launchpad.net/bugs/ -Forwarded: (no|not-needed|) -Applied-Upstream: , (|commit:) -Reviewed-By: Last-Update: 2024-01-10 --- vtk9-9.3.0+dfsg1.orig/GUISupport/Qt/QVTKOpenGLWindow.cxx diff --git a/debian/patches/121_add_support_for_loong64.patch b/debian/patches/121_add_support_for_loong64.patch new file mode 100644 index 000000000..ee9fbea96 --- /dev/null +++ b/debian/patches/121_add_support_for_loong64.patch @@ -0,0 +1,22 @@ +Description: add support for loongarch64 +Upstream: https://gitlab.kitware.com/seanm/vtk/-/commit/886b536a0d0bb3694951e09169a52896d585c517 +Author: Dandan Zhang + +--- +Last-Update: 2023-10-24 + +Index: VTK-9.3.0/Utilities/KWIML/vtkkwiml/include/kwiml/abi.h +=================================================================== +--- VTK-9.3.0.orig/Utilities/KWIML/vtkkwiml/include/kwiml/abi.h ++++ VTK-9.3.0/Utilities/KWIML/vtkkwiml/include/kwiml/abi.h +@@ -413,6 +413,10 @@ suppression macro KWIML_ABI_NO_VERIFY wa + #elif defined(__loongarch64) + # define KWIML_ABI_ENDIAN_ID KWIML_ABI_ENDIAN_ID_LITTLE + ++/* LoongArch */ ++#elif defined(__loongarch64) ++# define KWIML_ABI_ENDIAN_ID KWIML_ABI_ENDIAN_ID_LITTLE ++ + /* Motorola 68k */ + #elif defined(__m68k__) || defined(M68000) + # define KWIML_ABI_ENDIAN_ID KWIML_ABI_ENDIAN_ID_BIG diff --git a/debian/patches/130_fix_python_3.13.patch b/debian/patches/130_fix_python_3.13.patch new file mode 100644 index 000000000..31641fded --- /dev/null +++ b/debian/patches/130_fix_python_3.13.patch @@ -0,0 +1,1058 @@ +Description: Fix python 3.13 segfault +Author: Anton Gladky +Bug-Debian: https://bugs.debian.org/1092354 +Applied-Upstream: https://gitlab.kitware.com/vtk/vtk/-/merge_requests/11486 ; https://gitlab.kitware.com/vtk/vtk/-/merge_requests/11486 +Last-Update: 2025-01-28 + +--- vtk9-9.3.0+dfsg1.orig/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx ++++ vtk9-9.3.0+dfsg1/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx +@@ -96,6 +96,7 @@ wchar_t* vtk_Py_UTF8ToWide(const char* a + return result; + } + ++#if PY_VERSION_HEX < 0x03080000 + std::string vtk_Py_WideToUTF8(const wchar_t* arg) + { + std::string result; +@@ -109,6 +110,7 @@ std::string vtk_Py_WideToUTF8(const wcha + + return result; + } ++#endif + + std::vector>* GlobalInterpreters; + std::vector PythonPaths; +@@ -333,12 +335,21 @@ void SetupVTKPythonPaths(bool isolated) + if (vtklib.empty()) + { + VTKPY_DEBUG_MESSAGE( +- "`GetVTKVersion` library couldn't be found. Will use `Py_GetProgramName` next."); ++ "`GetVTKVersion` library couldn't be found. Will use `sys.executable` next."); + } + + if (vtklib.empty()) + { ++#if PY_VERSION_HEX >= 0x03080000 ++ vtkPythonScopeGilEnsurer gilEnsurer; ++ PyObject* executable_path = PySys_GetObject("executable"); ++ if (executable_path != Py_None) ++ { ++ vtklib = PyUnicode_AsUTF8AndSize(executable_path, nullptr); ++ } ++#else + vtklib = vtk_Py_WideToUTF8(Py_GetProgramName()); ++#endif + } + + vtklib = systools::CollapseFullPath(vtklib); +--- /dev/null ++++ vtk9-9.3.0+dfsg1/Utilities/PythonInterpreter/vtkPythonInterpreter.cxx.orig +@@ -0,0 +1,933 @@ ++// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen ++// SPDX-License-Identifier: BSD-3-Clause ++#include "vtkPythonInterpreter.h" ++#include "vtkPython.h" // this must be the first include. ++ ++#include "vtkBuild.h" ++#include "vtkCommand.h" ++#include "vtkLogger.h" ++#include "vtkNew.h" ++#include "vtkObjectFactory.h" ++#include "vtkOutputWindow.h" ++#include "vtkPythonStdStreamCaptureHelper.h" ++#include "vtkResourceFileLocator.h" ++#include "vtkVersion.h" ++#include "vtkWeakPointer.h" ++#include "vtksys/Encoding.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(_WIN32) && !defined(__CYGWIN__) ++#define VTK_PATH_SEPARATOR "\\" ++#else ++#define VTK_PATH_SEPARATOR "/" ++#endif ++ ++#define VTKPY_DEBUG_MESSAGE(x) \ ++ vtkVLog(vtkLogger::ConvertToVerbosity(vtkPythonInterpreter::GetLogVerbosity()), x) ++#define VTKPY_DEBUG_MESSAGE_VV(x) \ ++ vtkVLog(vtkLogger::ConvertToVerbosity(vtkPythonInterpreter::GetLogVerbosity() + 1), x) ++ ++#if defined(_WIN32) && !defined(__CYGWIN__) && defined(VTK_BUILD_SHARED_LIBS) && \ ++ PY_VERSION_HEX >= 0x03080000 ++#define vtkPythonInterpreter_USE_DIRECTORY_COOKIE ++#endif ++ ++namespace ++{ ++ ++template ++class PoolT ++{ ++ std::vector Strings; ++ ++public: ++ ~PoolT() ++ { ++ for (T* astring : this->Strings) ++ { ++ PyMem_RawFree(astring); ++ } ++ } ++ ++ T* push_back(T* val) ++ { ++ this->Strings.push_back(val); ++ return val; ++ } ++ ++ T* pop_last() ++ { ++ if (this->Strings.empty()) ++ { ++ return nullptr; ++ } ++ T* last = *this->Strings.rbegin(); ++ this->Strings.pop_back(); ++ return last; ++ } ++}; ++ ++using StringPool = PoolT; ++using WCharStringPool = PoolT; ++ ++wchar_t* vtk_Py_UTF8ToWide(const char* arg) ++{ ++ wchar_t* result = nullptr; ++ if (arg != nullptr) ++ { ++ size_t length = vtksysEncoding_mbstowcs(nullptr, arg, 0); ++ if (length > 0) ++ { ++ result = (wchar_t*)PyMem_RawMalloc(sizeof(wchar_t) * (length + 1)); ++ vtksysEncoding_mbstowcs(result, arg, length + 1); ++ } ++ } ++ ++ return result; ++} ++ ++std::string vtk_Py_WideToUTF8(const wchar_t* arg) ++{ ++ std::string result; ++ size_t length = vtksysEncoding_wcstombs(nullptr, arg, 0); ++ if (length > 0) ++ { ++ std::vector chars(length + 1); ++ vtksysEncoding_wcstombs(chars.data(), arg, length + 1); ++ result.assign(chars.data(), length); ++ } ++ ++ return result; ++} ++ ++std::vector>* GlobalInterpreters; ++std::vector PythonPaths; ++ ++void NotifyInterpreters(unsigned long eventid, void* calldata = nullptr) ++{ ++ std::vector>::iterator iter; ++ for (iter = GlobalInterpreters->begin(); iter != GlobalInterpreters->end(); ++iter) ++ { ++ if (iter->GetPointer()) ++ { ++ iter->GetPointer()->InvokeEvent(eventid, calldata); ++ } ++ } ++} ++ ++inline void vtkPrependPythonPath(const char* pathtoadd) ++{ ++ VTKPY_DEBUG_MESSAGE("adding module search path " << pathtoadd); ++ vtkPythonScopeGilEnsurer gilEnsurer; ++ PyObject* path = PySys_GetObject("path"); ++ PyObject* newpath = PyUnicode_FromString(pathtoadd); ++ ++ // avoid adding duplicate paths. ++ if (PySequence_Contains(path, newpath) == 0) ++ { ++ PyList_Insert(path, 0, newpath); ++ } ++ Py_DECREF(newpath); ++} ++} ++ ++VTK_ABI_NAMESPACE_BEGIN ++// Schwarz counter idiom for GlobalInterpreters object ++static unsigned int vtkPythonInterpretersCounter; ++vtkPythonGlobalInterpreters::vtkPythonGlobalInterpreters() ++{ ++ if (vtkPythonInterpretersCounter++ == 0) ++ { ++ GlobalInterpreters = new std::vector>(); ++ } ++} ++ ++vtkPythonGlobalInterpreters::~vtkPythonGlobalInterpreters() ++{ ++ if (--vtkPythonInterpretersCounter == 0) ++ { ++ delete GlobalInterpreters; ++ GlobalInterpreters = nullptr; ++ } ++} ++ ++bool vtkPythonInterpreter::InitializedOnce = false; ++bool vtkPythonInterpreter::CaptureStdin = false; ++bool vtkPythonInterpreter::RedirectOutput = true; ++bool vtkPythonInterpreter::ConsoleBuffering = false; ++std::string vtkPythonInterpreter::StdErrBuffer; ++std::string vtkPythonInterpreter::StdOutBuffer; ++int vtkPythonInterpreter::LogVerbosity = vtkLogger::VERBOSITY_TRACE; ++ ++#if PY_VERSION_HEX >= 0x03000000 ++struct CharDeleter ++{ ++ void operator()(wchar_t* str) { PyMem_RawFree(str); } ++}; ++#endif ++ ++vtkStandardNewMacro(vtkPythonInterpreter); ++//------------------------------------------------------------------------------ ++vtkPythonInterpreter::vtkPythonInterpreter() ++{ ++ GlobalInterpreters->push_back(this); ++} ++ ++//------------------------------------------------------------------------------ ++vtkPythonInterpreter::~vtkPythonInterpreter() ++{ ++ // We need to check that GlobalInterpreters has not been deleted yet. It can be ++ // deleted prior to a call to this destructor if another static object with a ++ // reference to a vtkPythonInterpreter object deletes that object after ++ // GlobalInterpreters has been destructed. It all depends on the destruction order ++ // of the other static object and GlobalInterpreters. ++ if (!GlobalInterpreters) ++ { ++ return; ++ } ++ std::vector>::iterator iter; ++ for (iter = GlobalInterpreters->begin(); iter != GlobalInterpreters->end(); ++iter) ++ { ++ if (*iter == this) ++ { ++ GlobalInterpreters->erase(iter); ++ break; ++ } ++ } ++} ++ ++//------------------------------------------------------------------------------ ++bool vtkPythonInterpreter::IsInitialized() ++{ ++ return (Py_IsInitialized() != 0); ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::PrintSelf(ostream& os, vtkIndent indent) ++{ ++ this->Superclass::PrintSelf(os, indent); ++} ++ ++//------------------------------------------------------------------------------ ++bool vtkPythonInterpreter::Initialize(int initsigs /*=0*/) ++{ ++ return vtkPythonInterpreter::InitializeWithArgs(initsigs, 0, nullptr); ++} ++ ++#if PY_VERSION_HEX >= 0x03080000 ++static WCharStringPool PythonProgramName; ++#endif ++ ++//------------------------------------------------------------------------------ ++// Ensure that Python is pre-initialized enough for VTK to do its ++// initialization. Must be called before any `PyMem_*` calls are made. ++static bool vtkPythonPreConfig() ++{ ++ // Guard against doing this multiple times. ++ static bool done = false; ++ if (done) ++ { ++ return false; ++ } ++ done = true; ++ ++#if PY_VERSION_HEX >= 0x03080000 ++ PyStatus status; ++ PyPreConfig preconfig; ++ PyPreConfig_InitPythonConfig(&preconfig); ++ ++ preconfig.allocator = PYMEM_ALLOCATOR_NOT_SET; ++ preconfig.utf8_mode = 1; ++ ++ status = Py_PreInitialize(&preconfig); ++ if (PyStatus_Exception(status)) ++ { ++ Py_ExitStatusException(status); ++ } ++ ++ return preconfig.isolated; ++#else ++ return Py_FrozenFlag; ++#endif ++} ++ ++//------------------------------------------------------------------------------ ++namespace ++{ ++/** ++ * Since vtkPythonInterpreter is often used outside CPython executable, e.g. ++ * vtkpython, the default logic to locate Python standard libraries used by ++ * Python (which depends on the executable path) may fail or pickup incorrect ++ * Python libs. This methods address the issue by setting program name to help ++ * guide Python's default prefix/exec_prefix searching logic. ++ */ ++void SetupPythonPrefix(bool isolated) ++{ ++ using systools = vtksys::SystemTools; ++ ++ // Check if we're using an isolated Python. ++ if (isolated) ++ { ++ VTKPY_DEBUG_MESSAGE("Isolated Python detected; skipping setting up of program path."); ++ return; ++ } ++ ++ std::string pythonlib = vtkGetLibraryPathForSymbol(Py_InitializeEx); ++ if (pythonlib.empty()) ++ { ++ VTKPY_DEBUG_MESSAGE("static Python build or `Py_InitializeEx` library couldn't be found. " ++ "Set `PYTHONHOME` if Python standard library fails to load."); ++ return; ++ } ++ ++ const std::string newprogramname = ++ systools::GetFilenamePath(pythonlib) + VTK_PATH_SEPARATOR "vtkpython"; ++ VTKPY_DEBUG_MESSAGE("calling vtkPythonInterpreter::SetProgramName(" ++ << newprogramname << ") to aid in setup of Python prefix."); ++ vtkPythonInterpreter::SetProgramName(newprogramname.c_str()); ++} ++ ++#ifdef vtkPythonInterpreter_USE_DIRECTORY_COOKIE ++PyObject* DLLDirectoryCookie = nullptr; ++ ++void CloseDLLDirectoryCookie() ++{ ++ if (DLLDirectoryCookie) ++ { ++ if (PyObject_HasAttrString(DLLDirectoryCookie, "close")) ++ { ++ PyObject* result = PyObject_CallMethod(DLLDirectoryCookie, "close", nullptr); ++ Py_XDECREF(result); ++ } ++ Py_XDECREF(DLLDirectoryCookie); ++ DLLDirectoryCookie = nullptr; ++ } ++} ++#endif ++ ++//------------------------------------------------------------------------------ ++/** ++ * Add paths to VTK's Python modules. ++ */ ++void SetupVTKPythonPaths(bool isolated) ++{ ++ // Check if we're using an isolated Python. ++ if (isolated) ++ { ++ VTKPY_DEBUG_MESSAGE("Isolated Python detected; skipping setting up of `vtk` package."); ++ return; ++ } ++ ++ using systools = vtksys::SystemTools; ++ std::string vtklib = vtkGetLibraryPathForSymbol(GetVTKVersion); ++ if (vtklib.empty()) ++ { ++ VTKPY_DEBUG_MESSAGE( ++ "`GetVTKVersion` library couldn't be found. Will use `Py_GetProgramName` next."); ++ } ++ ++ if (vtklib.empty()) ++ { ++ vtklib = vtk_Py_WideToUTF8(Py_GetProgramName()); ++ } ++ ++ vtklib = systools::CollapseFullPath(vtklib); ++ const std::string vtkdir = systools::GetFilenamePath(vtklib); ++ ++#if defined(_WIN32) && !defined(__CYGWIN__) && defined(VTK_BUILD_SHARED_LIBS) ++ // On Windows, based on how the executable is run, we end up failing to load ++ // pyd files due to inability to load dependent dlls. This seems to overcome ++ // the issue. ++ if (!vtkdir.empty()) ++ { ++#if PY_VERSION_HEX >= 0x03080000 ++ vtkPythonScopeGilEnsurer gilEnsurer(false, true); ++ CloseDLLDirectoryCookie(); ++ PyObject* os = PyImport_ImportModule("os"); ++ if (os) ++ { ++ PyObject* add_dll_directory = PyObject_GetAttrString(os, "add_dll_directory"); ++ if (add_dll_directory && PyCallable_Check(add_dll_directory)) ++ { ++ PyObject* newpath = PyUnicode_FromString(vtkdir.c_str()); ++ DLLDirectoryCookie = PyObject_CallFunctionObjArgs(add_dll_directory, newpath, nullptr); ++ Py_XDECREF(newpath); ++ } ++ ++ Py_XDECREF(add_dll_directory); ++ } ++ ++ Py_XDECREF(os); ++#else ++ std::string env_path; ++ if (systools::GetEnv("PATH", env_path)) ++ { ++ env_path = vtkdir + ";" + env_path; ++ } ++ else ++ { ++ env_path = vtkdir; ++ } ++ systools::PutEnv(std::string("PATH=") + env_path); ++#endif ++ } ++#endif ++ ++#if defined(VTK_BUILD_SHARED_LIBS) ++ vtkPythonInterpreter::PrependPythonPath(vtkdir.c_str(), "vtkmodules/__init__.py"); ++#else ++ // since there may be other packages not zipped (e.g. mpi4py), we added path to _vtk.zip ++ // to the search path as well. ++ vtkPythonInterpreter::PrependPythonPath(vtkdir.c_str(), "_vtk.zip", /*add_landmark*/ false); ++ vtkPythonInterpreter::PrependPythonPath(vtkdir.c_str(), "_vtk.zip", /*add_landmark*/ true); ++#endif ++} ++} ++ ++//------------------------------------------------------------------------------ ++bool vtkPythonInterpreter::InitializeWithArgs(int initsigs, int argc, char* argv[]) ++{ ++ bool isolated = vtkPythonPreConfig(); ++ ++ if (Py_IsInitialized() == 0) ++ { ++ // guide the mechanism to locate Python standard library, if possible. ++ SetupPythonPrefix(isolated); ++ bool signals_installed = initsigs != 0; ++ ++ // Need two copies of args, because programs might modify the first ++ using OwnedWideString = std::unique_ptr; ++ std::vector argvForPython; ++ std::vector argvCleanup; ++ for (int i = 0; i < argc; i++) ++ { ++ OwnedWideString argCopy(vtk_Py_UTF8ToWide(argv[i]), CharDeleter()); ++ if (argCopy == nullptr) ++ { ++ fprintf(stderr, ++ "Fatal vtkpython error: " ++ "unable to decode the command line argument #%i\n", ++ i + 1); ++ return false; ++ } ++ ++ argvForPython.push_back(argCopy.get()); ++ argvCleanup.emplace_back(std::move(argCopy)); ++ } ++ argvForPython.push_back(nullptr); ++ ++#if PY_VERSION_HEX < 0x03080000 ++ Py_InitializeEx(initsigs); ++ // setup default argv. Without this, code snippets that check `sys.argv` may ++ // fail when run in embedded VTK Python environment. ++ PySys_SetArgvEx(argc, argvForPython.data(), 0); ++ ++ isolated = Py_FrozenFlag; ++#else ++ PyConfig config; ++ PyStatus status; ++ PyConfig_InitPythonConfig(&config); ++ config.install_signal_handlers = initsigs; ++ config.program_name = PythonProgramName.pop_last(); ++ status = PyConfig_SetArgv(&config, argc, argvForPython.data()); ++ if (PyStatus_IsError(status)) ++ { ++ PyConfig_Clear(&config); ++ return false; ++ } ++ ++ status = Py_InitializeFromConfig(&config); ++ if (PyStatus_IsError(status)) ++ { ++ PyConfig_Clear(&config); ++ return false; ++ } ++ isolated = config.pathconfig_warnings == 0; ++ PyConfig_Clear(&config); ++#endif ++ ++#ifdef VTK_PYTHON_FULL_THREADSAFE ++#if PY_VERSION_HEX < 0x03090000 ++ // In Python 3.9 and higher, PyEval_ThreadsInitialized() and ++ // PyEval_InitThreads() are deprecated and do nothing. ++ // GIL initialization is handled by Py_InitializeEx(). ++ int threadInit = PyEval_ThreadsInitialized(); ++ if (!threadInit) ++ { ++ PyEval_InitThreads(); // initialize and acquire GIL ++ } ++#endif ++ // Always release GIL, as it has been acquired either by PyEval_InitThreads ++ // prior to Python 3.7 or by Py_InitializeEx in Python 3.7 and after ++ PyEval_SaveThread(); ++#endif ++ ++#ifdef SIGINT ++ if (signals_installed) ++ { ++ // Put default SIGINT handler back after Py_Initialize/Py_InitializeEx. ++ signal(SIGINT, SIG_DFL); ++ } ++#endif ++ } ++ ++ if (!vtkPythonInterpreter::InitializedOnce) ++ { ++ vtkPythonInterpreter::InitializedOnce = true; ++ ++ // HACK: Calling PyRun_SimpleString for the first time for some reason results in ++ // a "\n" message being generated which is causing the error dialog to ++ // popup. So we flush that message out of the system before setting up the ++ // callbacks. ++ vtkPythonInterpreter::RunSimpleString(""); ++ ++ // Redirect Python's stdout and stderr and stdin - GIL protected operation ++ if (vtkPythonInterpreter::RedirectOutput) ++ { ++ // Setup handlers for stdout/stdin/stderr. ++ vtkPythonStdStreamCaptureHelper* wrapperOut = NewPythonStdStreamCaptureHelper(false); ++ vtkPythonStdStreamCaptureHelper* wrapperErr = NewPythonStdStreamCaptureHelper(true); ++ vtkPythonScopeGilEnsurer gilEnsurer; ++ PySys_SetObject("stdout", reinterpret_cast(wrapperOut)); ++ PySys_SetObject("stderr", reinterpret_cast(wrapperErr)); ++ PySys_SetObject("stdin", reinterpret_cast(wrapperOut)); ++ Py_DECREF(wrapperOut); ++ Py_DECREF(wrapperErr); ++ } ++ ++ // We call this before processing any of Python paths added by the ++ // application using `PrependPythonPath`. This ensures that application ++ // specified paths are preferred to the ones `vtkPythonInterpreter` adds. ++ SetupVTKPythonPaths(isolated); ++ ++ for (size_t cc = 0; cc < PythonPaths.size(); cc++) ++ { ++ vtkPrependPythonPath(PythonPaths[cc].c_str()); ++ } ++ ++ NotifyInterpreters(vtkCommand::EnterEvent); ++ return true; ++ } ++ ++ return false; ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::Finalize() ++{ ++ if (Py_IsInitialized() != 0) ++ { ++ NotifyInterpreters(vtkCommand::ExitEvent); ++ vtkPythonScopeGilEnsurer gilEnsurer(false, true); ++#ifdef vtkPythonInterpreter_USE_DIRECTORY_COOKIE ++ CloseDLLDirectoryCookie(); ++#endif ++ // Py_Finalize will take care of releasing gil ++ Py_Finalize(); ++ } ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::SetProgramName(const char* programname) ++{ ++ vtkPythonPreConfig(); ++ if (programname) ++ { ++#if PY_VERSION_HEX >= 0x03080000 ++ if (wchar_t* argv0 = vtk_Py_UTF8ToWide(programname)) ++ { ++ PythonProgramName.push_back(argv0); ++ } ++ else ++ { ++ fprintf(stderr, ++ "Fatal vtkpython error: " ++ "unable to decode the program name\n"); ++ wchar_t* empty = (wchar_t*)PyMem_RawMalloc(sizeof(wchar_t)); ++ empty[0] = 0; ++ PythonProgramName.push_back(empty); ++ } ++#else ++ // From Python Docs: The argument should point to a zero-terminated character ++ // string in static storage whose contents will not change for the duration of ++ // the program's execution. No code in the Python interpreter will change the ++ // contents of this storage. ++ wchar_t* argv0 = vtk_Py_UTF8ToWide(programname); ++ if (argv0 == nullptr) ++ { ++ fprintf(stderr, ++ "Fatal vtkpython error: " ++ "unable to decode the program name\n"); ++ static wchar_t empty[1] = { 0 }; ++ argv0 = empty; ++ Py_SetProgramName(argv0); ++ } ++ else ++ { ++ static WCharStringPool wpool; ++ Py_SetProgramName(wpool.push_back(argv0)); ++ } ++#endif ++ } ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::PrependPythonPath(const char* dir) ++{ ++ if (!dir) ++ { ++ return; ++ } ++ ++ std::string out_dir = dir; ++ ++#if defined(_WIN32) && !defined(__CYGWIN__) ++ // Convert slashes for this platform. ++ std::replace(out_dir.begin(), out_dir.end(), '/', '\\'); ++#endif ++ ++ if (Py_IsInitialized() == 0) ++ { ++ // save path for future use. ++ PythonPaths.push_back(out_dir); ++ return; ++ } ++ ++ // Append the path to the python sys.path object. ++ vtkPrependPythonPath(out_dir.c_str()); ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::PrependPythonPath( ++ const char* anchor, const char* landmark, bool add_landmark) ++{ ++ const std::vector prefixes = { ++ VTK_PYTHON_SITE_PACKAGES_SUFFIX ++#if defined(__APPLE__) ++ // if in an App bundle, the `sitepackages` dir is /Contents/Python ++ , ++ "Contents/Python" ++#endif ++ , ++ "." ++ }; ++ ++ vtkNew locator; ++ locator->SetLogVerbosity(vtkPythonInterpreter::GetLogVerbosity() + 1); ++ std::string path = locator->Locate(anchor, prefixes, landmark); ++ if (!path.empty()) ++ { ++ if (add_landmark) ++ { ++ path = path + "/" + landmark; ++ } ++ vtkPythonInterpreter::PrependPythonPath(path.c_str()); ++ } ++} ++ ++//------------------------------------------------------------------------------ ++int vtkPythonInterpreter::PyMain(int argc, char** argv) ++{ ++ vtksys::SystemTools::EnableMSVCDebugHook(); ++ ++ int count_v = 0; ++ for (int cc = 0; cc < argc; ++cc) ++ { ++ if (argv[cc] && strcmp(argv[cc], "-v") == 0) ++ { ++ ++count_v; ++ } ++ if (argv[cc] && strcmp(argv[cc], "-vv") == 0) ++ { ++ count_v += 2; ++ } ++ } ++ ++ if (count_v > 0) ++ { ++ // change the vtkPythonInterpreter's log verbosity. We only touch it ++ // if the command line arguments explicitly requested a certain verbosity. ++ vtkPythonInterpreter::SetLogVerbosity(vtkLogger::VERBOSITY_INFO); ++ vtkLogger::SetStderrVerbosity(vtkLogger::ConvertToVerbosity(count_v - 1)); ++ } ++ ++ vtkLogger::Init(argc, argv, nullptr); // since `-v` and `-vv` are parsed as Python verbosity flags ++ // and not log verbosity flags. ++ ++ // Need two copies of args, because the first array may be modified elsewhere. ++ using OwnedCString = std::unique_ptr; ++ std::vector argvForPython; ++ std::vector argvCleanup; ++ for (int i = 0; i < argc; i++) ++ { ++ if (!argv[i]) ++ { ++ continue; ++ } ++ if (strcmp(argv[i], "--enable-bt") == 0) ++ { ++ vtksys::SystemInformation::SetStackTraceOnError(1); ++ continue; ++ } ++ if (strcmp(argv[i], "-V") == 0) ++ { ++ // print out VTK version and let argument pass to Py_RunMain(). At which ++ // point, Python will print its version and exit. ++ cout << vtkVersion::GetVTKSourceVersion() << endl; ++ } ++ ++ OwnedCString argCopy(strdup(argv[i]), &std::free); ++ if (argCopy == nullptr) ++ { ++ fprintf(stderr, ++ "Fatal vtkpython error: " ++ "unable to copy the command line argument #%i\n", ++ i + 1); ++ return 1; ++ } ++ ++ argvForPython.push_back(argCopy.get()); ++ argvCleanup.emplace_back(std::move(argCopy)); ++ } ++ int argvForPythonSize = static_cast(argvForPython.size()); ++ argvForPython.push_back(nullptr); ++ ++ vtkPythonInterpreter::InitializeWithArgs(1, argvForPythonSize, argvForPython.data()); ++ ++#if PY_VERSION_HEX >= 0x03070000 && PY_VERSION_HEX < 0x03080000 ++ // Python 3.7.0 has a bug where Py_InitializeEx (called above) followed by ++ // Py_Main (at the end of this block) causes a crash. Gracefully exit with ++ // failure if we're using 3.7.0 and suggest getting the newest 3.7.x release. ++ // See for details. ++ { ++ bool is_ok = true; ++ vtkPythonScopeGilEnsurer gilEnsurer(false, true); ++ PyObject* sys = PyImport_ImportModule("sys"); ++ if (sys) ++ { ++ // XXX: Check sys.implementation.name == 'cpython'? ++ ++ PyObject* version_info = PyObject_GetAttrString(sys, "version_info"); ++ if (version_info) ++ { ++ PyObject* major = PyObject_GetAttrString(version_info, "major"); ++ PyObject* minor = PyObject_GetAttrString(version_info, "minor"); ++ PyObject* micro = PyObject_GetAttrString(version_info, "micro"); ++ ++ auto py_number_cmp = [](PyObject* obj, long expected) { ++ return obj && PyLong_Check(obj) && PyLong_AsLong(obj) == expected; ++ }; ++ ++ // Only 3.7.0 has this issue. Any failures to get the version ++ // information is OK; we'll just crash later anyways if the version is ++ // bad. ++ is_ok = !py_number_cmp(major, 3) || !py_number_cmp(minor, 7) || !py_number_cmp(micro, 0); ++ ++ Py_XDECREF(micro); ++ Py_XDECREF(minor); ++ Py_XDECREF(major); ++ } ++ ++ Py_XDECREF(version_info); ++ } ++ ++ Py_XDECREF(sys); ++ ++ if (!is_ok) ++ { ++ std::cerr << "Python 3.7.0 has a known issue that causes a crash with a " ++ "specific API usage pattern. This has been fixed in 3.7.1 and all " ++ "newer 3.7.x Python releases. Exiting now to avoid the crash." ++ << std::endl; ++ return 1; ++ } ++ } ++#endif ++ ++#if PY_VERSION_HEX < 0x03080000 ++ // Need two copies of args, because programs might modify the first ++ using OwnedWideString = std::unique_ptr; ++ std::vector argvForPythonWide; ++ std::vector argvCleanupWide; ++ for (size_t i = 0; i < argvCleanup.size(); i++) ++ { ++ OwnedWideString argCopy(vtk_Py_UTF8ToWide(argvCleanup[i].get()), CharDeleter()); ++ if (argCopy == nullptr) ++ { ++ fprintf(stderr, ++ "Fatal vtkpython error: " ++ "unable to decode the command line argument #%zu\n", ++ i + 1); ++ return 1; ++ } ++ ++ argvForPythonWide.push_back(argCopy.get()); ++ argvCleanupWide.emplace_back(std::move(argCopy)); ++ } ++ int argvForPythonWideSize = static_cast(argvForPythonWide.size()); ++ argvForPythonWide.push_back(nullptr); ++ ++ vtkPythonScopeGilEnsurer gilEnsurer(false, true); ++ return Py_Main(argvForPythonWideSize, argvForPythonWide.data()); ++#else ++ vtkPythonScopeGilEnsurer gilEnsurer(false, true); ++ return Py_RunMain(); ++#endif ++} ++ ++//------------------------------------------------------------------------------ ++int vtkPythonInterpreter::RunSimpleString(const char* script) ++{ ++ vtkPythonInterpreter::Initialize(1); ++ vtkPythonInterpreter::ConsoleBuffering = true; ++ ++ // The embedded python interpreter cannot handle DOS line-endings, see ++ // http://sourceforge.net/tracker/?group_id=5470&atid=105470&func=detail&aid=1167922 ++ std::string buffer = script ? script : ""; ++ buffer.erase(std::remove(buffer.begin(), buffer.end(), '\r'), buffer.end()); ++ ++ // The cast is necessary because PyRun_SimpleString() hasn't always been const-correct ++ int pyReturn; ++ { ++ vtkPythonScopeGilEnsurer gilEnsurer; ++ pyReturn = PyRun_SimpleString(buffer.c_str()); ++ } ++ ++ vtkPythonInterpreter::ConsoleBuffering = false; ++ if (!vtkPythonInterpreter::StdErrBuffer.empty()) ++ { ++ vtkOutputWindow::GetInstance()->DisplayErrorText(vtkPythonInterpreter::StdErrBuffer.c_str()); ++ NotifyInterpreters( ++ vtkCommand::ErrorEvent, const_cast(vtkPythonInterpreter::StdErrBuffer.c_str())); ++ vtkPythonInterpreter::StdErrBuffer.clear(); ++ } ++ if (!vtkPythonInterpreter::StdOutBuffer.empty()) ++ { ++ vtkOutputWindow::GetInstance()->DisplayText(vtkPythonInterpreter::StdOutBuffer.c_str()); ++ NotifyInterpreters( ++ vtkCommand::SetOutputEvent, const_cast(vtkPythonInterpreter::StdOutBuffer.c_str())); ++ vtkPythonInterpreter::StdOutBuffer.clear(); ++ } ++ ++ return pyReturn; ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::SetCaptureStdin(bool val) ++{ ++ vtkPythonInterpreter::CaptureStdin = val; ++} ++ ++//------------------------------------------------------------------------------ ++bool vtkPythonInterpreter::GetCaptureStdin() ++{ ++ return vtkPythonInterpreter::CaptureStdin; ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::SetRedirectOutput(bool redirect) ++{ ++ vtkPythonInterpreter::RedirectOutput = redirect; ++} ++ ++//------------------------------------------------------------------------------ ++bool vtkPythonInterpreter::GetRedirectOutput() ++{ ++ return vtkPythonInterpreter::RedirectOutput; ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::WriteStdOut(const char* txt) ++{ ++ if (vtkPythonInterpreter::ConsoleBuffering) ++ { ++ vtkPythonInterpreter::StdOutBuffer += std::string(txt); ++ } ++ else ++ { ++ vtkOutputWindow::GetInstance()->DisplayText(txt); ++ NotifyInterpreters(vtkCommand::SetOutputEvent, const_cast(txt)); ++ } ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::FlushStdOut() {} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::WriteStdErr(const char* txt) ++{ ++ if (vtkPythonInterpreter::ConsoleBuffering) ++ { ++ vtkPythonInterpreter::StdErrBuffer += std::string(txt); ++ } ++ else ++ { ++ vtkOutputWindow::GetInstance()->DisplayErrorText(txt); ++ NotifyInterpreters(vtkCommand::ErrorEvent, const_cast(txt)); ++ } ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::FlushStdErr() {} ++ ++//------------------------------------------------------------------------------ ++vtkStdString vtkPythonInterpreter::ReadStdin() ++{ ++ if (!vtkPythonInterpreter::CaptureStdin) ++ { ++ vtkStdString string; ++ cin >> string; ++ return string; ++ } ++ vtkStdString string; ++ NotifyInterpreters(vtkCommand::UpdateEvent, &string); ++ return string; ++} ++ ++//------------------------------------------------------------------------------ ++void vtkPythonInterpreter::SetLogVerbosity(int val) ++{ ++ vtkPythonInterpreter::LogVerbosity = vtkLogger::ConvertToVerbosity(val); ++} ++ ++//------------------------------------------------------------------------------ ++int vtkPythonInterpreter::GetLogVerbosity() ++{ ++ return vtkPythonInterpreter::LogVerbosity; ++} ++ ++#if defined(_WIN32) ++//------------------------------------------------------------------------------ ++vtkWideArgsConverter::vtkWideArgsConverter(int argc, wchar_t* wargv[]) ++{ ++ this->Argc = argc; ++ for (int i = 0; i < argc; i++) ++ { ++ std::string str = vtksys::Encoding::ToNarrow(wargv[i]); ++ char* cstr = vtksys::SystemTools::DuplicateString(str.c_str()); ++ Args.push_back(cstr); ++ MemCache.push_back(cstr); ++ } ++ Args.push_back(nullptr); ++} ++ ++//------------------------------------------------------------------------------ ++vtkWideArgsConverter::~vtkWideArgsConverter() ++{ ++ for (auto cstr : MemCache) ++ { ++ delete[] cstr; ++ } ++} ++#endif ++VTK_ABI_NAMESPACE_END +--- vtk9-9.3.0+dfsg1.orig/Utilities/PythonInterpreter/vtkPythonStdStreamCaptureHelper.h ++++ vtk9-9.3.0+dfsg1/Utilities/PythonInterpreter/vtkPythonStdStreamCaptureHelper.h +@@ -16,7 +16,8 @@ VTK_ABI_NAMESPACE_BEGIN + struct vtkPythonStdStreamCaptureHelper + { + PyObject_HEAD +- int softspace; // Used by print to keep track of its state. ++ int softspace; // Used by print to keep track of its state. ++ const char* Encoding; // Encoding, set to "utf-8" + bool DumpToError; + + void Write(const char* string) +@@ -84,6 +85,9 @@ static PyMemberDef vtkPythonStdStreamCap + { VTK_PYTHON_MEMBER_DEF_STR("softspace"), T_INT, + offsetof(vtkPythonStdStreamCaptureHelper, softspace), 0, + VTK_PYTHON_MEMBER_DEF_STR("Placeholder so print can keep state.") }, ++ { VTK_PYTHON_MEMBER_DEF_STR("encoding"), T_STRING, ++ offsetof(vtkPythonStdStreamCaptureHelper, Encoding), READONLY, ++ VTK_PYTHON_MEMBER_DEF_STR("Text encoding for file.") }, + { nullptr, 0, 0, 0, nullptr } + }; + +@@ -250,6 +254,7 @@ static vtkPythonStdStreamCaptureHelper* + PyObject_New(vtkPythonStdStreamCaptureHelper, &vtkPythonStdStreamCaptureHelperType); + if (wrapper) + { ++ wrapper->Encoding = "utf-8"; + wrapper->DumpToError = for_stderr; + } + +--- vtk9-9.3.0+dfsg1.orig/Wrapping/Python/vtkmodules/test/Testing.py ++++ vtk9-9.3.0+dfsg1/Wrapping/Python/vtkmodules/test/Testing.py +@@ -515,8 +515,10 @@ def test(cases): + """ + # Make the test suites from the arguments. + suites = [] +- for case in cases: +- suites.append(unittest.makeSuite(case[0], case[1])) ++ loader = unittest.TestLoader() ++ # the "name" is ignored (it was always just 'test') ++ for test,name in cases: ++ suites.append(loader.loadTestsFromTestCase(test)) + test_suite = unittest.TestSuite(suites) + + # Now run the tests. +--- vtk9-9.3.0+dfsg1.orig/Wrapping/PythonCore/PyVTKNamespace.cxx ++++ vtk9-9.3.0+dfsg1/Wrapping/PythonCore/PyVTKNamespace.cxx +@@ -112,8 +112,10 @@ PyObject* PyVTKNamespace_New(const char* + { + // make sure python has readied the type object + PyType_Ready(&PyVTKNamespace_Type); +- // call the allocator provided by python for this type +- self = PyVTKNamespace_Type.tp_alloc(&PyVTKNamespace_Type, 0); ++ // call the superclass new function ++ PyObject* empty = PyTuple_New(0); ++ self = PyVTKNamespace_Type.tp_base->tp_new(&PyVTKNamespace_Type, empty, nullptr); ++ Py_DECREF(empty); + // call the superclass init function + PyObject* pyname = PyUnicode_FromString(name); + PyObject* args = PyTuple_Pack(1, pyname); +--- vtk9-9.3.0+dfsg1.orig/Wrapping/PythonCore/PyVTKTemplate.cxx ++++ vtk9-9.3.0+dfsg1/Wrapping/PythonCore/PyVTKTemplate.cxx +@@ -761,8 +761,10 @@ PyObject* PyVTKTemplate_New(const char* + { + // make sure python has readied the type object + PyType_Ready(&PyVTKTemplate_Type); +- // call the allocator provided by python for this type +- PyObject* self = PyVTKTemplate_Type.tp_alloc(&PyVTKTemplate_Type, 0); ++ // call the superclass new function ++ PyObject* empty = PyTuple_New(0); ++ PyObject* self = PyVTKTemplate_Type.tp_base->tp_new(&PyVTKTemplate_Type, empty, nullptr); ++ Py_DECREF(empty); + // call the superclass init function + PyObject* pyname = PyUnicode_FromString(name); + PyObject* pydoc = PyUnicode_FromString(docstring); diff --git a/debian/patches/42_fix_octree_node.patch b/debian/patches/42_fix_octree_node.patch new file mode 100644 index 000000000..5956e9521 --- /dev/null +++ b/debian/patches/42_fix_octree_node.patch @@ -0,0 +1,13 @@ +Description: Fix undefined variable name in octree_node + +--- vtk9-9.3.0+dfsg1.orig/Utilities/octree/octree/octree_node.txx ++++ vtk9-9.3.0+dfsg1/Utilities/octree/octree/octree_node.txx +@@ -210,7 +210,7 @@ const octree_node& octree_no + { + throw std::domain_error("Attempt to access children of an octree leaf node."); + } +- return this->_M_chilren[child]; ++ return this->m_children[child]; + } + + /**\brief Return a reference to a child node. diff --git a/debian/patches/netcdf-4.9.3.patch b/debian/patches/netcdf-4.9.3.patch new file mode 100644 index 000000000..57aa25c85 --- /dev/null +++ b/debian/patches/netcdf-4.9.3.patch @@ -0,0 +1,172 @@ +Description: Replace _FillValue by NC_FillValue for NetCDF 4.9.3. +Author: Bas Couwenberg + +--- a/IO/MINC/vtkMINC.h ++++ b/IO/MINC/vtkMINC.h +@@ -178,7 +178,7 @@ use it. + #define MIvalid_range "valid_range" + #define MIvalid_max "valid_max" + #define MIvalid_min "valid_min" +-#define MI_FillValue "_FillValue" ++#define MI_FillValue "NC_FillValue" + #define MItitle "title" + #define MIhistory "history" + +--- a/IO/NetCDF/vtkNetCDFCFWriter.cxx ++++ b/IO/NetCDF/vtkNetCDFCFWriter.cxx +@@ -442,7 +442,7 @@ public: + status = NC_NOERR; + if (std::string(arrayName).rfind("vtk", 0) > 0) + { +- // for an array that starts with vtk we don't specify _FillValue ++ // for an array that starts with vtk we don't specify NC_FillValue + switch (vtkType) + { + case VTK_CHAR: +@@ -451,34 +451,34 @@ public: + if (fillValue != NC_FILL_INT) + { + unsigned char fillByte = fillValue; +- status = nc_put_att(ncid, attributeid, "_FillValue", NC_BYTE, 1, &fillByte); ++ status = nc_put_att(ncid, attributeid, "NC_FillValue", NC_BYTE, 1, &fillByte); + } + break; + case VTK_SHORT: + if (fillValue != NC_FILL_SHORT) + { + short fillShort = fillValue; +- status = nc_put_att_short(ncid, attributeid, "_FillValue", NC_SHORT, 1, &fillShort); ++ status = nc_put_att_short(ncid, attributeid, "NC_FillValue", NC_SHORT, 1, &fillShort); + } + break; + case VTK_INT: + if (fillValue != NC_FILL_INT) + { +- status = nc_put_att_int(ncid, attributeid, "_FillValue", NC_INT, 1, &fillValue); ++ status = nc_put_att_int(ncid, attributeid, "NC_FillValue", NC_INT, 1, &fillValue); + } + break; + case VTK_FLOAT: + if (fillValue != NC_FILL_INT) + { + float fillFloat = fillValue; +- status = nc_put_att_float(ncid, attributeid, "_FillValue", NC_FLOAT, 1, &fillFloat); ++ status = nc_put_att_float(ncid, attributeid, "NC_FillValue", NC_FLOAT, 1, &fillFloat); + } + break; + case VTK_DOUBLE: + if (fillValue != NC_FILL_INT) + { + double fillDouble = fillValue; +- status = nc_put_att_double(ncid, attributeid, "_FillValue", NC_DOUBLE, 1, &fillDouble); ++ status = nc_put_att_double(ncid, attributeid, "NC_FillValue", NC_DOUBLE, 1, &fillDouble); + } + break; + default: +@@ -489,7 +489,7 @@ public: + if (status) + { + std::ostringstream ostr; +- ostr << "Error nc_put_att_xxx " << arrayName << ":_FillValue: " << nc_strerror(status); ++ ostr << "Error nc_put_att_xxx " << arrayName << ":NC_FillValue: " << nc_strerror(status); + throw std::runtime_error(ostr.str()); + } + } +--- a/IO/NetCDF/vtkNetCDFReader.cxx ++++ b/IO/NetCDF/vtkNetCDFReader.cxx +@@ -867,7 +867,7 @@ int vtkNetCDFReader::LoadVariable(int nc + + // Check for a fill value. + size_t attribLength; +- if ((nc_inq_attlen(ncFD, varId, "_FillValue", &attribLength) == NC_NOERR) && (attribLength == 1)) ++ if ((nc_inq_attlen(ncFD, varId, "NC_FillValue", &attribLength) == NC_NOERR) && (attribLength == 1)) + { + if (this->ReplaceFillValueWithNan) + { +@@ -875,7 +875,7 @@ int vtkNetCDFReader::LoadVariable(int nc + if (dataArray->GetDataType() == VTK_FLOAT) + { + float fillValue; +- nc_get_att_float(ncFD, varId, "_FillValue", &fillValue); ++ nc_get_att_float(ncFD, varId, "NC_FillValue", &fillValue); + std::replace(reinterpret_cast(dataArray->GetVoidPointer(0)), + reinterpret_cast(dataArray->GetVoidPointer(dataArray->GetNumberOfTuples())), + fillValue, static_cast(vtkMath::Nan())); +@@ -883,7 +883,7 @@ int vtkNetCDFReader::LoadVariable(int nc + else if (dataArray->GetDataType() == VTK_DOUBLE) + { + double fillValue; +- nc_get_att_double(ncFD, varId, "_FillValue", &fillValue); ++ nc_get_att_double(ncFD, varId, "NC_FillValue", &fillValue); + std::replace(reinterpret_cast(dataArray->GetVoidPointer(0)), + reinterpret_cast(dataArray->GetVoidPointer(dataArray->GetNumberOfTuples())), + fillValue, vtkMath::Nan()); +--- a/IO/NetCDF/vtkNetCDFReader.h ++++ b/IO/NetCDF/vtkNetCDFReader.h +@@ -107,7 +107,7 @@ public: + + ///@{ + /** +- * If on, any float or double variable read that has a _FillValue attribute ++ * If on, any float or double variable read that has a NC_FillValue attribute + * will have that fill value replaced with a not-a-number (NaN) value. The + * advantage of setting these to NaN values is that, if implemented properly + * by the system and careful math operations are used, they can implicitly be +--- a/IO/NetCDF/vtkNetCDFUGRIDReader.cxx ++++ b/IO/NetCDF/vtkNetCDFUGRIDReader.cxx +@@ -508,10 +508,10 @@ bool vtkNetCDFUGRIDReader::ParseHeader() + if (this->NodesPerFace > 3) // may be mixed mesh + { + if (!this->CheckError( +- nc_get_att(this->NcId, this->FaceVarId, "_FillValue", &this->FaceFillValue))) ++ nc_get_att(this->NcId, this->FaceVarId, "NC_FillValue", &this->FaceFillValue))) + { +- vtkErrorMacro("_FillValue attribute missing - The connectivity variable has to specify a " +- "_FillValue attribute because it has more than 3 nodes per face"); ++ vtkErrorMacro("NC_FillValue attribute missing - The connectivity variable has to specify a " ++ "NC_FillValue attribute because it has more than 3 nodes per face"); + return false; + } + } +@@ -859,7 +859,7 @@ struct DataArrayExtractor + if (replaceFill && (std::is_same::value || std::is_same::value)) + { + T fillValue{}; +- if (nc_get_att(NcId, var, "_FillValue", &fillValue) != NC_NOERR) ++ if (nc_get_att(NcId, var, "NC_FillValue", &fillValue) != NC_NOERR) + { + vtkDebugWithObjectMacro(output, "No fill value defined"); + return; +--- a/IO/NetCDF/vtkNetCDFUGRIDReader.h ++++ b/IO/NetCDF/vtkNetCDFUGRIDReader.h +@@ -76,7 +76,7 @@ public: + + ///@{ + /** +- * If on, any float or double variable read that has a _FillValue attribute ++ * If on, any float or double variable read that has a NC_FillValue attribute + * will have that fill value replaced with a not-a-number (NaN) value. The + * advantage of setting these to NaN values is that, if implemented properly + * by the system and careful math operations are used, they can implicitly be +--- a/ThirdParty/exodusII/vtkexodusII/src/ex_put_prop.c ++++ b/ThirdParty/exodusII/vtkexodusII/src/ex_put_prop.c +@@ -243,7 +243,7 @@ int ex_put_prop(int exoid, ex_entity_typ + vals[0] = 0; /* fill value */ + /* create attribute to cause variable to fill with zeros per routine spec + */ +- if ((status = nc_put_att_longlong(exoid, propid, _FillValue, int_type, 1, vals)) != NC_NOERR) { ++ if ((status = nc_put_att_longlong(exoid, propid, NC_FillValue, int_type, 1, vals)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to create property name fill attribute in file id %d", exoid); + ex_err_fn(exoid, __func__, errmsg, status); +--- a/ThirdParty/exodusII/vtkexodusII/src/ex_put_prop_names.c ++++ b/ThirdParty/exodusII/vtkexodusII/src/ex_put_prop_names.c +@@ -172,7 +172,7 @@ int ex_put_prop_names(int exoid, ex_enti + + /* create attribute to cause variable to fill with zeros per routine spec + */ +- if ((status = nc_put_att_longlong(exoid, propid, _FillValue, int_type, 1, vals)) != NC_NOERR) { ++ if ((status = nc_put_att_longlong(exoid, propid, NC_FillValue, int_type, 1, vals)) != NC_NOERR) { + snprintf(errmsg, MAX_ERR_LENGTH, + "ERROR: failed to create property name fill attribute in file id %d", exoid); + ex_err_fn(exoid, __func__, errmsg, status); diff --git a/debian/patches/series b/debian/patches/series index 62197a20e..b3eb0c0fc 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,7 +1,9 @@ +09_newer_expat.patch 10_matplotlib.patch 20_do_not_link_against_socket.patch 30_drop_medical_example.patch 40_vtkpython-9.patch +42_fix_octree_node.patch 50_fix_python-modules_path.patch 60_fix_path_perl.patch 84_vtkQWidgetTexture_no_vtkOpenGLCheckErrorMacro.patch @@ -10,3 +12,6 @@ 98_fix_mpi4py.py 99_fix_ftbfs.patch 100_add_missing_gl_header.patch +121_add_support_for_loong64.patch +130_fix_python_3.13.patch +netcdf-4.9.3.patch diff --git a/debian/rules b/debian/rules index 7f3a1be52..a607f6af7 100755 --- a/debian/rules +++ b/debian/rules @@ -1,10 +1,11 @@ #!/usr/bin/make -f BUILDDIR = $(CURDIR)/debian/build -DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) +include /usr/share/dpkg/architecture.mk -nojava_archs=hppa hurd-i386 kfreebsd-i386 kfreebsd-amd64 -ifneq ($(DEB_BUILD_ARCH),$(filter $(DEB_BUILD_ARCH), $(nojava_archs))) +nojava_archs=hppa +nojava_os=hurd +ifeq (,$(filter $(DEB_BUILD_ARCH), $(nojava_archs))$(filter $(DEB_BUILD_ARCH_OS), $(nojava_os))) export JAVA_HOME=/usr/lib/jvm/default-java extra_flags += -DVTK_WRAP_JAVA=ON endif @@ -14,8 +15,9 @@ ifneq (,$(filter $(DEB_HOST_ARCH), armel m68k mips mipsel powerpc sh4)) export DEB_LDFLAGS_MAINT_APPEND += -Wl,--no-as-needed -latomic -Wl,--as-needed endif -notbb_archs=hurd-i386 kfreebsd-i386 kfreebsd-amd64 -ifneq ($(DEB_BUILD_ARCH),$(filter $(DEB_BUILD_ARCH), $(notbb_archs))) +notbb_archs= +notbb_os=hurd +ifeq (,$(filter $(DEB_BUILD_ARCH), $(notbb_archs))$(filter $(DEB_BUILD_ARCH_OS), $(notbb_os))) extra_flags += -DVTK_SMP_IMPLEMENTATION_TYPE:STRING="TBB" else extra_flags += -DVTK_SMP_IMPLEMENTATION_TYPE:STRING="OpenMP" @@ -45,6 +47,7 @@ extra_flags += \ -DVTK_GROUP_ENABLE_Views:STRING="YES" \ -DVTK_GROUP_ENABLE_MPI:STRING="YES" \ -DVTK_GROUP_ENABLE_Imaging:STRING="YES" \ + -DVTK_MODULE_ENABLE_VTK_IOGeoJSON:STRING="YES" \ -DVTK_MODULE_ENABLE_VTK_RenderingQt:STRING="YES" \ -DVTK_MODULE_ENABLE_VTK_RenderingTk:STRING="YES" \ -DVTK_MODULE_ENABLE_VTK_utf8:STRING="YES" \ @@ -71,8 +74,7 @@ extra_flags += \ -DVTK_MODULE_USE_EXTERNAL_VTK_tiff:BOOL=ON \ -DVTK_MODULE_USE_EXTERNAL_VTK_utf8:BOOL=ON \ -DVTK_MODULE_USE_EXTERNAL_VTK_zlib:BOOL=ON \ - -DVTK_PYTHON_VERSION:STRING=3 \ - -DVTK_USE_TK=ON \ + -DVTK_USE_TK=OFF \ -DVTK_WRAP_PYTHON=ON \ -DVTK_MODULE_ENABLE_VTK_RenderingContextOpenGL2=YES \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -- 2.30.2